package com.zxw.xml.util;

import cn.hutool.core.date.DateUtil;
import com.zxw.xml.annotation.XmlAttributeName;
import com.zxw.xml.annotation.XmlRootElementName;
import com.zxw.xml.annotation.XmlTagName;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @projectName: ruoyi
 * @package: com.ruoyi.common.utils.xml
 * @className: ObjectToXmlConverter
 * @author: zhangxuewei
 * @description: TODO
 * @date: 2023/7/6 13:15
 * @version: 1.0
 */
public class ObjectToXmlConverter {
    public static String convertToXml(Object object) {
        Document document = DocumentHelper.createDocument();
        XmlRootElementName an = object.getClass().getDeclaredAnnotation(XmlRootElementName.class);
        Element rootElement = document.addElement(ObjectUtils.isEmpty(an.tagName()) ? object.getClass().getSimpleName() : an.tagName());
        convertObjectToElements(object, rootElement, document);
        return document.asXML();
    }

    private static void convertObjectToElements(Object object, Element parentElement, Document document) {
        for (Field field : object.getClass().getDeclaredFields()) {
            try {
                field.setAccessible(true);
                Object value = field.get(object);
                // 如果为空，给个空字符串，这样即使 属性为null 也会生成标签
                if (value == null) {
                    value = "";
                }
                if (!(field.getName().indexOf("this") > -1)) {
                    if (!ObjectUtils.isEmpty(field.getAnnotation(XmlAttributeName.class))) {
                        parentElement.addAttribute(ObjectUtils.isEmpty(field.getAnnotation(XmlAttributeName.class)) ? field.getName() : field.getAnnotation(XmlAttributeName.class).tagName(), value.toString());
                    } else {
                        Element element = parentElement.addElement(ObjectUtils.isEmpty(field.getAnnotation(XmlTagName.class)) ? field.getName() : field.getAnnotation(XmlTagName.class).tagName());
                        if (value instanceof String || value instanceof Integer || value instanceof Boolean || value instanceof Long || value instanceof BigDecimal) {
                            element.setText(String.valueOf(value));
                        } else if (value instanceof Double || value instanceof Float) {
                            element.setText(Double.toString(Double.valueOf(value.toString())));
                        } else if (value instanceof Date) {
                            element.setText(DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss"));
                        } else if (value instanceof List) {
                            for (Object listValue : (List) value) {
                                Element elementL;
                                if (!ObjectUtils.isEmpty(field.getAnnotation(XmlTagName.class)) && !ObjectUtils.isEmpty(field.getAnnotation(XmlTagName.class).arrayObjTagName()))
                                    elementL = element.addElement(field.getAnnotation(XmlTagName.class).arrayObjTagName());
                                else
                                    elementL = element.addElement("item");
                                convertObjectToElements(listValue, elementL, document);
                            }
                        } else if (value instanceof Map) {
                            for (Map.Entry<String, Object> mapEntry : ((Map<String, Object>) value).entrySet()) {
                                Element mapElement = element.addElement(mapEntry.getKey());
                                convertObjectToElements(mapEntry.getValue(), mapElement, document);
                            }
                        } else {
                            convertObjectToElements(value, element, document);
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
